import {_decorator, instantiate, Prefab, randomRangeInt, UITransform} from 'cc';
import {CardPoolMgr} from './CardPoolMgr';
import {OrderPoolMgr} from './OrderPoolMgr';

import {BaseCard, CardInMountain} from '../models/Card';
import UCard from '../components/UCard';
import {ManagerBase} from './ManagerBase';
import {GridList} from '../utils/GridList';

const { ccclass, property } = _decorator;

@ccclass('CardMountainMgr')
export class CardMountainMgr extends ManagerBase {
    private _cards: GridList<CardInMountain> = null;

    @property(Prefab)
    cardPrefab: Prefab = null;

    protected onLoad() {
        this._cards = new GridList<CardInMountain>();
    }

    protected onEnable() {

    }

    protected onDisable(): void {

    }

    get cardsUI(): UCard[] {
        return this.node.children.map(node => node.getComponent(UCard));
    }

    async initData(level): Promise<void> {
        const d = await this.reload(level);
        this._cards.setData(d);
    }

    initUI(): void {
        this.refreshUI();
        this.refreshVisibility();
    }

    refreshUI() {
        let count = 0;
        const ls = this._cards.flatten();
        for (let i = 0; i < ls.length; i++) {
            const card = ls[i];
            let cardUI = this.cardsUI[i];
            if (!cardUI) {
                let cnp = instantiate(this.cardPrefab);
                this.node.addChild(cnp);
                cardUI = cnp.getComponent(UCard);
            }

            cardUI.init(card.layerid, card.index);
            cardUI.refresh(card);
            ++count;
        }
    }

    refreshUIAt(row: number, Col: number, card: CardInMountain) {

    }

    refreshUIByUid(cardData) {
        let card = this.getCardUIByUid(cardData.uid);
        card.fixCard(cardData);
    }

    refreshVisibility() {

        // 按zIndex或位置排序卡牌
        const sortedCards = this.cardsUI;

        // 记录每张卡牌是否被遮挡
        const visibilityMap = new Map<UCard, boolean>();

        // 从最底层开始检查
        for (let i = 0; i < sortedCards.length; i++) {
            const currentCard = sortedCards[i];
            let isBlocked = false;

            // 检查是否有上层卡牌遮挡当前卡牌
            for (let j = i + 1; j < sortedCards.length; j++) {
                const upperCard = sortedCards[j];
                if (this.isCardOverlap(currentCard, upperCard)) {
                    isBlocked = true;
                    break;
                }
            }

            visibilityMap.set(currentCard, isBlocked);
        }

        // 更新卡牌状态
        sortedCards.forEach(card => {
            const isBlocked = visibilityMap.get(card);
            if (!isBlocked) {
                card.isOpen = true; // 被遮挡的翻面(正面)，未被遮挡的背面


                let cardData = this.getCardDataByUid(card.uid);
                if (cardData) {
                    cardData.isOpen = true;
                }
            }

        });
    }

    getCardByIndex(index: number): CardInMountain {
        // 处理不规则二维数组的情况
        let currentIndex = 0;
        for (let row = 0; row < this._cards.rows; row++) {
            const rowLength = this._cards.getColsInRow(row);
            if (index < currentIndex + rowLength) {
                // 找到了对应的行，计算列索引
                const col = index - currentIndex;
                return this._cards.get(row, col);
            }
            currentIndex += rowLength;
        }

        // 如果索引超出范围，返回null或抛出异常
        console.error(`Index ${index} out of range for card mountain`);
        return null;
    }

    async reload(filename: string): Promise<CardInMountain[][]> {
        const cm = CardPoolMgr.getInstance();
        return await cm.generateMap(filename);
    }

    reset(): void {

    }

    getOpenCards(): CardInMountain[] {
        let ret = [];
        for (let i = 0; i < this._cards.rows; i++) {
            let row = this._cards.getRow(i);
            for (let j = 0; j < row.length; j++) {
                const card = this._cards.get(i, j);
                if (card.isOpen) {
                    ret.push(card);
                }
            }
        }
        return ret;
    }

    getCardDataByUid(uid: number): CardInMountain {
        for (let i = 0; i < this._cards.rows; i++) {
            for (let j = 0; j < this._cards.getColsInRow(i); j++) {
                const card = this._cards.get(i, j);
                if (card.uid == uid) {
                    return card;
                }
            }
        }
    }

    getCardByPos(row: number, col: number): CardInMountain {
        return this._cards.get(row, col);
    }

    shuffle(needCards: number[]): boolean {
        // 洗牌
        let cs = this._cards.flatten();
        let adjustCount = 0;
        let curIndex = cs.length - 1;

        let ret = false
        for (let i = 0; i < needCards.length; i++) {
            const src = needCards[i];
            const srcCard = this.getCardDataByUid(src);
            if (srcCard) {
                const desCard = cs[curIndex];
                if (srcCard.uid != desCard.uid) {
                    CardInMountain.swapUidAndValue(srcCard, desCard);
                }

                ++adjustCount;
                --curIndex;

                ret = true;
            }
        }

        for (let i = 0; i < this._cards.rows - 1; i++) {
            let len = this._cards.getColsInRow(i);
            let halfLen = len / 2;
            for (let j = 0; j < halfLen; j++) {
                let aim = randomRangeInt(halfLen, len - 1);
                CardInMountain.swapUidAndValue(this._cards.get(i, j), this._cards.get(i, aim));
            }
        }

        this.refreshUI();
        return ret;
    }

    tips(needCards: number[]): boolean {
        const op = OrderPoolMgr.getInstance();
        const curOrders = op.getUsedOrder();
        const openCards = this.getOpenCards();
        for (let i = 0; i < openCards.length; i++) {
            for (let j = 0; j < curOrders.length; j++) {
                let order = curOrders[j];
                if (order.isFit(openCards[i]) >= 0) {
                    const cui = this.getCardUIByUid(openCards[i].uid);
                    cui.select();
                    return true;
                }
            }
        }
        return false;
    }

    getCardUIByUid(uid: number): UCard {
        return this.cardsUI.find(card => card.uid == uid);
    }

    private isCardOverlap(cardA: UCard, cardB: UCard): boolean {
        // 获取卡牌的UITransform组件
        const transformA = cardA.node.getComponent(UITransform);
        const transformB = cardB.node.getComponent(UITransform);

        // 获取世界空间下的包围盒
        const aBox = transformA.getBoundingBoxToWorld();
        const bBox = transformB.getBoundingBoxToWorld();

        // 检测包围盒是否相交
        return aBox.intersects(bBox);
    }

    removeCardByUid(uid: number): boolean {
        let cardData = this.getCardDataByUid(uid);
        if (!cardData)
            return false;
        let cardUI = this.getCardUIByUid(uid);
        cardUI.node.removeFromParent();
        this.removeCardData(uid);
        this.refreshVisibility();
    }

    removeCardData(uid) {
        for (let i = 0; i < this._cards.rows; i++) {
            const cols = this._cards.getColsInRow(i);
            for (let j = cols -1; j >= 0; --j) {
                const card = this._cards.get(i, j);
                if (card.uid == uid) {
                    for (let k = j; k < cols - 1; k++) {
                        const ck = this._cards.get(i, j+1,);
                        ck.index = k;
                    }
                    this._cards.removeAt(i, j);
                    return;
                }
            }
        }
    }

    correctCard(cardData: BaseCard, orderId: number) {
        let cardUI = this.getCardUIByUid(cardData.uid);
        let card = this.getCardDataByUid(cardData.uid);
        if (!cardUI || !card)
            return;
        console.log('correctCard cardMountain', card.uid, 'to', cardData.uid, 'orderId:', orderId);
        card.setValue(cardData.cardId);
        card.orderId = orderId;
        this.refreshUIByUid(cardData);
        return;
    }

    showAllCards() {
        for (let card of this.cardsUI) {
            card.isOpen = true;
        }
    }
}